﻿using Gasgoo.ShareLibrary.Framework.iDataProvider;
using Gasgoo.ShareLibrary.Framework.Options;
using Orleans.Runtime;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Gasgoo.DataProvider.BySqlSugar
{
    public class DataStorageProviderBySuagr : IDataStorageProvider
    {
        readonly SqlSugarClient client;
        const AbstractDataEntity? entity = null;

        public DataStorageProviderBySuagr(string providerName, IServiceProvider provider)
        {
            this.client = provider.GetRequiredServiceByName<SqlSugarClient>(providerName);
        }

        public Task AddOrUpdateAsync(string grainType, string key, string keyExtension, object state, Type stateType)
        {
            this.client.Queryable<EndpointsOptions>()
                .Where(endpoint => endpoint.Port == 1)
                .WhereIF(false, null)
                .GroupBy(endpoint => endpoint.GatewayPort)
                .OrderBy(endpoint => endpoint.Port)
                .OrderByDescending(endpoint => endpoint.GatewayPort)
                .OrderByIF(false, null)
                //.ToPageListAsync()
                .ToListAsync();



            client.StorageableByObject(state).ExecuteCommand();
            if (((AbstractDataEntity)state).CreateDate == DateTime.MinValue)
            {
                ((AbstractDataEntity)state).CreateDate = DateTime.Now;
            }
            return Task.CompletedTask;
        }

        public async Task<object> GetAsync(string grainType, string key, string keyExtension, Type stateType)
        {
            var res = await this.client.QueryableByObject(stateType).InSingleAsync(key);
            if (res == null)
            {
                var ins = (AbstractDataEntity)Activator.CreateInstance(stateType);
                ins.PrimaryKey = key;
                res = ins;
            }
            return res;
        }

        public async Task RemoveAsync(string grainType, string key, string keyExtension, object state)
        {
            await this.client.DeleteableByObject(state).ExecuteCommandAsync();
        }

        public Task<List<T>> QueryableAsync<T>(Queryable<T> queryable) where T : AbstractDataEntity
        {
            var query = this.client.Queryable<T>();
            if (queryable.Where != null && queryable.Where.Any())
            {
                foreach (var item in queryable.Where)
                {
                    query = query.Where(item);
                }
            }

            if (queryable.GroupBy != null && queryable.GroupBy.Any())
            {
                foreach (var item in queryable.GroupBy)
                {
                    query = query.GroupBy(item);
                }
            }

            if (queryable.OrderBy != null && queryable.OrderBy.Any())
            {
                foreach (var item in queryable.OrderBy)
                {
                    if (item.Key == OrderByEnum.Asc)
                        query = query.OrderBy(item.Value);
                    else
                        query = query.OrderByDescending(item.Value);
                }
            }

            if (queryable.Page != null)
                return query.ToPageListAsync(queryable.Page.PageNumber, queryable.Page.PageSize);
            else
                return query.ToListAsync();
        }
    }
}
